import Vue from 'vue';
/**
 * 获取对象类型
 * @public
 * @param {Object} obj
 * @returns {String} type
 */
export function isType(obj) {
  if (obj instanceof Element) {
    return 'Element';
  }

  return /\b((?!object)\w)+\b/.exec(Object.prototype.toString.call(obj))[0];
}

/**
 * 是否空对象
 * @param {any} value 判断对象
 * @returns {Boolean}
 */
export function isEmpty(value) {
  if (!value) return true;
  const type = isType(value);
  if (type === 'Object') return !Object.keys(value).length;
  if (type === 'Array') return !value.length;
  if (type === 'Number') return !(value > 0 && value < Number.POSITIVE_INFINITY);
  if (type === 'String') {
    return ['false', 'undefined', 'null', 'NaN', '-Infinity', 'Infinity', '{}', '[]'].some(
      (item) => value === item
    );
  }
  return !value;
}

/**
 * 对象序列化为url参数
 * @public
 * @param {Object} obj
 * @param {boolean} isEncode
 * @returns {String} 序列化后的字符串
 */
export function serializeToUrl(obj, isEncode = true) {
  const params = [];
  const keys = Object.keys(obj);

  for (let i = 0; i < keys.length; i++) {
    const key = keys[i];
    const value = obj[key];

    if (isEmpty(value)) continue;

    const val = isEncode ? encodeURIComponent(value) : value;

    params.push(`${key}=${val}`);
  }

  return params.join('&');
}

/**
 * a=b&b=d 转换成对象类型
 * @private
 * @param {String} search  a=b&b=d
 * @returns {Object} {{}}
 */
function searchToObj(search) {
  if (isEmpty(search) || isType(search) !== 'String') return {};

  const searchArr = search.split('&');
  const params = {};
  // eslint-disable-next-line no-plusplus
  for (let i = 0; i < searchArr.length; i++) {
    const pair = searchArr[i].split('=');
    // eslint-disable-next-line no-continue
    if (pair[1] === 'undefined') continue;
    params[pair[0]] = decodeURIComponent(pair[1] || '');
  }
  return params;
}

/**
 * 获取url参数集
 * @public
 * @param {String?} [url = window.location.href]
 * @param {Boolean?} [includeHash = true] 是否包含hash
 * @returns {({} & {}) | {}}
 */
export function getUrlParams(url, includeHash) {
  // eslint-disable-next-line prefer-rest-params
  const args = arguments;
  let vIncludeHash = includeHash;
  if (args.length === 1 && isType(args[0]) !== 'String') {
    vIncludeHash = !!args[0];
  }

  const vUrl = isType(url) === 'String' ? url : window.location.href;
  vIncludeHash = isType(vIncludeHash) === 'Boolean' ? vIncludeHash : true;

  let searchUrl = vUrl;
  let isSearch = '';
  let searchObj = '';
  const isHash = vUrl.indexOf('#');

  if (isHash > -1) searchUrl = vUrl.slice(0, isHash);
  isSearch = searchUrl.indexOf('?');
  if (isSearch > -1) searchObj = searchUrl.slice(isSearch + 1);

  searchObj = searchToObj(searchObj);

  if (!vIncludeHash || isHash === -1) return searchObj;

  let hashObj = '';
  const hashUrl = vUrl.slice(isHash);
  const isHashSearch = hashUrl.indexOf('?');
  if (isHashSearch > -1) hashObj = hashUrl.slice(isHashSearch + 1);

  hashObj = searchToObj(hashObj);

  return { ...searchObj, ...hashObj };
}

/**
 * 加密文本内容
 * @param {String} text 必填，需加密的文本内容
 * @param {String} [symbol = '*'] 可选，加密的符号
 * @param {Array} [ignore = []] 可选，忽略加密文本
 * @param {Function?} callback 可选，回调函数。返回true加密，false不加密
 * @returns {string|*} 加密后的文本
 */
export function encryptText(text, symbol, ignore, callback) {
  if (isEmpty(text) || isType(text) !== 'String') return '';

  // eslint-disable-next-line prefer-rest-params
  const args = arguments;
  const vSymbol = isType(symbol) === 'String' ? symbol : '*';
  const vIgnore = isType(ignore) === 'Array' ? ignore : [];
  const vCallback = isType(callback) === 'Function' ? callback : (index) => index !== 0;

  if (vIgnore.includes(text)) return text;

  let encrypt = '';
  // eslint-disable-next-line no-plusplus
  for (let i = 0; i < text.length; i++) {
    encrypt += vCallback(text[i], i, text) ? vSymbol : text[i];
  }

  return encrypt;
}

/**
 * 是否外部地址
 * @param {string} path
 * @returns {Boolean}
 */
export function isExternalUrl(path) {
  return /^(https?:|mailto:|tel:)/.test(path);
}

/**
 * 复制对象或集合
 * @param {} || list data
 * @returns {} || list copydata
 */
export function copy(data) {
  return JSON.parse(JSON.stringify(data));
}

/**
 * 组件间事件调用
 *
 */
export const EventBus = new Vue();
